类型转换详解
隐式转换(自动转换)
算术转换(表达式中)
混合类型参与运算时,C++ 会将较小的类型提升为较大的类型,再做运算:
char / short → int → unsigned int → long → unsigned long
→ long long → unsigned long long → float → double → long double
整型 + 浮点 → 浮点:
int i = 3;
double d = 1.5;
auto result = i + d; // result 是 double,值为 4.5bool / char / short 参与算术时会先整型提升为 int,再计算。
赋值转换
把右侧值赋给左侧变量时,自动转为目标类型。可能丢失信息:
int i = 3.9; // i = 3,小数部分截断(不是四舍五入!)
float f = 1e300; // 超出 float 范围,结果未定义
bool b = -5; // b = true(非零即 true)
char c = 257; // 溢出,结果依赖实现(通常回绕为 1)C++11 的 {} 初始化会拒绝窄化转换(直接报错):
int x{3.9}; // 编译错误:narrowing conversion函数参数转换
传参时也会发生同样的隐式转换:
void foo(double x);
foo(3); // int 3 → double 3.0,自动提升显式转换(强制转换)
C 风格(不推荐)
(int)3.9 // 结果 3
(double)7 / 2 // 结果 3.5(先转再除)C++ 函数风格
int(3.9) // 结果 3,只是形式上像函数调用C++ 推荐:static_cast<>
static_cast<int>(3.9) // 3
static_cast<double>(7) / 2 // 3.5为什么推荐 static_cast<>?
- 在代码里视觉上很显眼,容易 grep 查找
- 只做编译期合法的转换,不会绕过类型系统
- 比 C 风格更安全,能被代码审查工具识别
四种具名转换(进阶)
C++ 还提供了四种用途更精确的转换,了解即可:
| 转换 | 用途 |
|---|---|
static_cast<T> | 编译期类型转换(最常用) |
const_cast<T> | 去掉 / 加上 const 修饰 |
reinterpret_cast<T> | 底层重新解释比特(危险,少用) |
dynamic_cast<T> | 运行期多态向下转型(需虚函数,后续章节讲) |
常见陷阱
// 陷阱 1:整数除法
int a = 7, b = 2;
double r = a / b; // r = 3.0,不是 3.5!除法已经发生在整型
double r2 = (double)a / b; // r2 = 3.5,先转再除
// 陷阱 2:截断不是四舍五入
int i = (int)3.9; // i = 3,不是 4
// 陷阱 3:无符号整数下溢
unsigned int u = 0;
u - 1; // 结果是 UINT_MAX(4294967295),不是 -1
// 陷阱 4:有符号溢出(未定义行为!)
int x = INT_MAX;
x + 1; // 未定义行为,不保证回绕